home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / misc / Fudgit233.lha / Source / src / readline / vi_mode.c < prev   
Encoding:
C/C++ Source or Header  |  1993-12-14  |  17.9 KB  |  959 lines

  1. /* vi_mode.c -- A vi emulation mode for Bash.
  2.  
  3.    Derived from code written by Jeff Sparkes (jeff1@????).
  4.  */
  5.  
  6. /* **************************************************************** */
  7. /*                                    */
  8. /*            VI Emulation Mode                */
  9. /*                                    */
  10. /* **************************************************************** */
  11.  
  12. /* Last string searched for from `/' or `?'. */
  13. static char *vi_last_search = (char *)NULL;
  14. static int vi_histpos;
  15.  
  16. /* Non-zero means enter insertion mode. */
  17. int vi_doing_insert = 0;
  18.  
  19. /* *** UNCLEAN *** */
  20. /* Command keys which do movement for xxx_to commands. */
  21. static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
  22.  
  23. /* Keymap used for vi replace characters.  Created dynamically since
  24.    rarely used. */
  25. static Keymap vi_replace_map = (Keymap)NULL;
  26.  
  27. /* The number of characters inserted in the last replace operation. */
  28. static vi_replace_count = 0;
  29.  
  30. /* some declarations */
  31. static void vi_done_inserting (void), rl_digit_loop1 (void),
  32.     rl_back_to_indent (void);
  33.  
  34. /* Yank the nth arg from the previous line into this line at point. */
  35. void rl_vi_yank_arg (int count, int dum1)
  36. {
  37.   rl_yank_nth_arg (count, 0);
  38. }
  39.  
  40. /* Search again for the last thing searched for. */
  41. void rl_vi_search_again (int ignore, int key)
  42. {
  43.   switch (key)
  44.     {
  45.     case 'n':
  46.       rl_vi_dosearch ((int) vi_last_search, -1);
  47.       break;
  48.  
  49.     case 'N':
  50.       rl_vi_dosearch ((int) vi_last_search, 1);
  51.       break;
  52.     }
  53. }
  54.  
  55. /* Do a vi style search. */
  56. void rl_vi_search (int count, int key)
  57. {
  58.   int dir, c, save_pos;
  59.   char *p;
  60.  
  61.   switch (key)
  62.     {
  63.     case '?':
  64.       dir = 1;
  65.       break;
  66.  
  67.     case '/':
  68.       dir = -1;
  69.       break;
  70.  
  71.     default:
  72.       ding ();
  73.       return;
  74.     }
  75.  
  76.   vi_histpos = hl_where_history ();
  77.   maybe_save_line ();
  78.   save_pos = rl_point;
  79.  
  80.   /* Reuse the line input buffer to read the search string. */
  81.   the_line[0] = 0;
  82.   rl_end = rl_point = 0;
  83.   p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
  84.  
  85.   sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
  86.  
  87.   rl_message (p, 0, 0);
  88.  
  89.   while (c = rl_read_key ())
  90.     {
  91.       switch (c)
  92.     {
  93.     case CTRL('H'):
  94.     case RUBOUT:
  95.       if (rl_point == 0)
  96.         {
  97.           maybe_unsave_line ();
  98.           rl_clear_message ();
  99.           rl_point = save_pos;
  100.           return;
  101.         }
  102.  
  103.     case CTRL('W'):
  104.     case CTRL('U'):
  105.       rl_dispatch (c, keymap);
  106.       break;
  107.  
  108.     case ESC:
  109.     case RETURN:
  110.     case NEWLINE:
  111.       goto dosearch;
  112.       break;
  113.  
  114.     case CTRL('C'):
  115.       maybe_unsave_line ();
  116.       rl_clear_message ();
  117.       rl_point = 0;
  118.       ding ();
  119.       return;
  120.  
  121.     default:
  122.       rl_insert (1, c);
  123.       break;
  124.     }
  125.       rl_redisplay ();
  126.     }
  127.  dosearch:
  128.   if (vi_last_search)
  129.     free (vi_last_search);
  130.  
  131.   vi_last_search = savestring (the_line);
  132.   rl_vi_dosearch ((int)the_line, dir);
  133. }
  134.  
  135. void rl_vi_dosearch (int cp, int dir)
  136. {
  137.   int old, save = vi_histpos;
  138.   HIST_ENTRY *h;
  139.   char *string = (char *)cp;
  140.  
  141.   if (string == 0 || *string == 0 || vi_histpos < 0)
  142.     {
  143.       ding ();
  144.       return;
  145.     }
  146.  
  147.   if ((save = hl_history_search_pos (string, dir, vi_histpos + dir)) == -1)
  148.     {
  149.       maybe_unsave_line ();
  150.       rl_clear_message ();
  151.       rl_point = 0;
  152.       ding ();
  153.       return;
  154.     }
  155.  
  156.   vi_histpos = save;
  157.  
  158.   old = hl_where_history ();
  159.   hl_history_set_pos (vi_histpos);
  160.   h = hl_current_history ();
  161.   hl_history_set_pos (old);
  162.  
  163.   strcpy (the_line, h->line);
  164.   rl_undo_list = (UNDO_LIST *)h->data;
  165.   rl_end = strlen (the_line);
  166.   rl_point = 0;
  167.   rl_clear_message ();
  168. }
  169.  
  170. /* Completion, from vi's point of view. */
  171. void rl_vi_complete (int ignore, int key)
  172. {
  173.   if ((rl_point < rl_end) && (!whitespace (the_line[rl_point])))
  174.     {
  175.       if (!whitespace (the_line[rl_point + 1]))
  176.     rl_vi_end_word (1, 'E');
  177.       rl_point++;
  178.     }
  179.  
  180.   if (key == '*')
  181.     rl_complete_internal ('*');
  182.   else
  183.     rl_complete (0, key);
  184.  
  185.   rl_vi_insertion_mode (0, 0);
  186. }
  187.  
  188. /* Previous word in vi mode. */
  189. void rl_vi_prev_word (int count, int key)
  190. {
  191.   if (count < 0)
  192.     {
  193.       rl_vi_next_word (-count, key);
  194.       return;
  195.     }
  196.  
  197.   if (uppercase_p (key))
  198.     rl_vi_bWord (count, 0);
  199.   else
  200.     rl_vi_bword (count, 0);
  201. }
  202.  
  203. /* Next word in vi mode. */
  204. void rl_vi_next_word (int count, int key)
  205. {
  206.   if (count < 0)
  207.     {
  208.       rl_vi_prev_word (-count, key);
  209.       return;
  210.     }
  211.  
  212.   if (uppercase_p (key))
  213.     rl_vi_fWord (count, 0);
  214.   else
  215.     rl_vi_fword (count, 0);
  216. }
  217.  
  218. /* Move to the end of the ?next? word. */
  219. void rl_vi_end_word (int count, int key)
  220. {
  221.   if (count < 0)
  222.     {
  223.       ding ();
  224.       return;
  225.     }
  226.  
  227.   if (uppercase_p (key))
  228.     rl_vi_eWord (count, 0);
  229.   else
  230.     rl_vi_eword (count, 0);
  231. }
  232.  
  233. /* Move forward a word the way that 'W' does. */
  234. /* Move forward a word the way that 'W' does. */
  235. void rl_vi_fWord (int count, int dum2)
  236. {
  237.   while (count-- && rl_point < (rl_end - 1))
  238.     {
  239.       /* Skip until whitespace. */
  240.       while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
  241.         rl_point++;
  242.  
  243.       /* Now skip whitespace. */
  244.       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
  245.         rl_point++;
  246.     }
  247. }
  248.  
  249. void rl_vi_bWord (int count, int dum2)
  250. {
  251.   while (count-- && rl_point > 0)
  252.     {
  253.       /* If we are at the start of a word, move back to whitespace so
  254.          we will go back to the start of the previous word. */
  255.       if (!whitespace (the_line[rl_point]) &&
  256.           whitespace (the_line[rl_point - 1]))
  257.         rl_point--;
  258.  
  259.       while (rl_point > 0 && whitespace (the_line[rl_point]))
  260.         rl_point--;
  261.  
  262.       if (rl_point > 0)
  263.         {
  264.           while (--rl_point >= 0 && !whitespace (the_line[rl_point]));
  265.           rl_point++;
  266.         }
  267.     }
  268. }
  269.  
  270. void rl_vi_eWord (int count, int dum2)
  271. {
  272.   while (count-- && rl_point < (rl_end - 1))
  273.     {
  274.       /* Move to white space. */
  275.       while (++rl_point < rl_end && whitespace (the_line[rl_point]))
  276.         ;
  277.  
  278.       if (rl_point && rl_point < rl_end)
  279.         {
  280.           /* Skip whitespace. */
  281.           while (rl_point < rl_end && whitespace (the_line[rl_point]))
  282.             rl_point++;
  283.  
  284.           /* Skip until whitespace. */
  285.           while (rl_point < rl_end && !whitespace (the_line[rl_point]))
  286.             rl_point++;
  287.  
  288.           /* Move back to the last character of the word. */
  289.           rl_point--;
  290.         }
  291.     }
  292. }
  293.  
  294. void rl_vi_fword (int count, int dum2)
  295. {
  296.   while (count-- && rl_point < (rl_end - 1))
  297.     {
  298.       /* Move to white space (really non-identifer). */
  299.       if (isident (the_line[rl_point]))
  300.         {
  301.           while (isident (the_line[rl_point]) && rl_point < rl_end)
  302.             rl_point++;
  303.         }
  304.       else /* if (!whitespace (the_line[rl_point])) */
  305.         {
  306.           while (!isident (the_line[rl_point]) &&
  307.                  !whitespace (the_line[rl_point]) && rl_point < rl_end)
  308.             rl_point++;
  309.         }
  310.  
  311.       /* Move past whitespace. */
  312.       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
  313.         rl_point++;
  314.     }
  315. }
  316.  
  317. void rl_vi_bword (int count, int dum2)
  318. {
  319.   while (count-- && rl_point > 0)
  320.     {
  321.       int last_is_ident;
  322.  
  323.       /* If we are at the start of a word, move back to a non-identifier
  324.          so we will go back to the start of the previous word. */
  325.       if (isident (the_line[rl_point]) && !isident (the_line[rl_point - 1]))
  326.         rl_point--;
  327.  
  328.       /* If this character and the previous character are `opposite', move
  329.          back so we don't get messed up by the rl_point++ down there in
  330.          the while loop.  Without this code, words like `l;' screw up the
  331.          function. */
  332.       last_is_ident = isident (the_line[rl_point - 1]);
  333.       if ((isident (the_line[rl_point]) && !last_is_ident) ||
  334.           (!isident (the_line[rl_point]) && last_is_ident))
  335.         rl_point--;
  336.  
  337.       while (rl_point > 0 && whitespace (the_line[rl_point]))
  338.         rl_point--;
  339.  
  340.       if (rl_point > 0)
  341.         {
  342.           if (isident (the_line[rl_point]))
  343.             while (--rl_point >= 0 && isident (the_line[rl_point]));
  344.           else
  345.             while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
  346.                    !whitespace (the_line[rl_point]));
  347.           rl_point++;
  348.         }
  349.     }
  350. }
  351.  
  352. void rl_vi_eword (int count, int dum2)
  353. {
  354.   while (count-- && rl_point < rl_end - 1)
  355.     {
  356.       while (++rl_point < rl_end && whitespace (the_line[rl_point]))
  357.         ;
  358.  
  359.       if (rl_point < rl_end)
  360.         {
  361.           if (isident (the_line[rl_point]))
  362.             while (++rl_point < rl_end && isident (the_line[rl_point]));
  363.           else
  364.             while (++rl_point < rl_end && !isident (the_line[rl_point])
  365.                    && !whitespace (the_line[rl_point]));
  366.           rl_point--;
  367.         }
  368.     }
  369. }
  370.  
  371. void rl_vi_insert_beg (int dum1, int dum2)
  372. {
  373.   rl_beg_of_line (0, 0);
  374.   rl_vi_insertion_mode (0, 0);
  375. }
  376.  
  377. void rl_vi_append_mode (int dum1, int dum2)
  378. {
  379.   if (rl_point < rl_end)
  380.     rl_point += 1;
  381.   rl_vi_insertion_mode (0, 0);
  382. }
  383.  
  384. void rl_vi_append_eol (int dum1, int dum2)
  385. {
  386.   rl_end_of_line (0, 0);
  387.   rl_vi_append_mode (0, 0);
  388. }
  389.  
  390. /* What to do in the case of C-d. */
  391. void rl_vi_eof_maybe (int count, int c)
  392. {
  393.   rl_newline (1, '\n');
  394. }
  395.  
  396. /* Insertion mode stuff. */
  397.  
  398. /* Switching from one mode to the other really just involves
  399.    switching keymaps. */
  400. void rl_vi_insertion_mode (int dum1, int dum2)
  401. {
  402.   keymap = vi_insertion_keymap;
  403. }
  404.  
  405. void rl_vi_movement_mode (int dum1, int dum2)
  406. {
  407.   if (rl_point > 0)
  408.     rl_backward (1, 0);
  409.  
  410.   keymap = vi_movement_keymap;
  411.   vi_done_inserting ();
  412. }
  413.  
  414. static void vi_done_inserting ()
  415. {
  416.   if (vi_doing_insert)
  417.     {
  418.       rl_end_undo_group ();
  419.       vi_doing_insert = 0;
  420.     }
  421. }
  422.  
  423. void rl_vi_arg_digit (count, c)
  424.      int count, c;
  425. {
  426.   if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
  427.     rl_beg_of_line(0, 0);
  428.   else
  429.     rl_digit_argument (count, c);
  430. }
  431.  
  432. /* Doesn't take an arg count in vi */
  433. void rl_vi_change_case (int ignore1, int ignore2)
  434. {
  435.   char c = 0;
  436.  
  437.   /* Don't try this on an empty line. */
  438.   if (rl_point >= rl_end - 1)
  439.     return;
  440.  
  441.   if (uppercase_p (the_line[rl_point]))
  442.     c = to_lower (the_line[rl_point]);
  443.   else if (lowercase_p (the_line[rl_point]))
  444.     c = to_upper (the_line[rl_point]);
  445.  
  446.   /* Vi is kind of strange here. */
  447.   if (c)
  448.     {
  449.       rl_begin_undo_group ();
  450.       rl_delete (1, c);
  451.       rl_insert (1, c);
  452.       rl_end_undo_group ();
  453.       rl_vi_check ();
  454.     }
  455.   else
  456.     rl_forward (1, 0);
  457. }
  458.  
  459. void rl_vi_put (int count, int key)
  460. {
  461.   if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
  462.     rl_forward (1, 0);
  463.  
  464.   rl_yank (0, 0);
  465.   rl_backward (1, 0);
  466. }
  467.  
  468. static void rl_vi_check (void)
  469. {
  470.   if (rl_point && rl_point == rl_end)
  471.     rl_point--;
  472. }
  473.  
  474. void rl_vi_column (int count, int dum2)
  475. {
  476.   if (count > rl_end)
  477.     rl_end_of_line (0, 0);
  478.   else
  479.     rl_point = count - 1;
  480. }
  481.  
  482. int rl_vi_domove (int key, int *nextkey)
  483. {
  484.   int c, save;
  485.  
  486.   rl_mark = rl_point;
  487.   c = rl_read_key ();
  488.   *nextkey = c;
  489.  
  490.   if (!member (c, vi_motion))
  491.     {
  492.       if (digit (c))
  493.     {
  494.       save = rl_numeric_arg;
  495.       rl_digit_loop1 ();
  496.       rl_numeric_arg *= save;
  497.     }
  498.       else if ((key == 'd' && c == 'd') ||
  499.            (key == 'c' && c == 'c'))
  500.     {
  501.       rl_mark = rl_end;
  502.       rl_beg_of_line(0, 0);
  503.       return (0);
  504.     }
  505.       else
  506.     return (-1);
  507.     }
  508.  
  509.   rl_dispatch (c, keymap);
  510.  
  511.   /* No change in position means the command failed. */
  512.   if (rl_mark == rl_point)
  513.     return (-1);
  514.  
  515.   if ((c == 'w' || c == 'W') && rl_point < rl_end)
  516.     rl_point--;
  517.  
  518.   if (rl_mark < rl_point)
  519.     exchange (rl_point, rl_mark);
  520.  
  521.   return (0);
  522. }
  523.  
  524. /* A simplified loop for vi. Don't dispatch key at end.
  525.    Don't recognize minus sign? */
  526. static void rl_digit_loop1 (void)
  527. {
  528.   int key, c;
  529.  
  530.   while (1)
  531.     {
  532.       rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
  533.       key = c = rl_read_key ();
  534.  
  535.       if (keymap[c].type == ISFUNC &&
  536.       keymap[c].function == rl_universal_argument)
  537.     {
  538.       rl_numeric_arg *= 4;
  539.       continue;
  540.     }
  541.  
  542.       c = UNMETA (c);
  543.       if (numeric (c))
  544.     {
  545.       if (rl_explicit_arg)
  546.         rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
  547.       else
  548.         rl_numeric_arg = (c - '0');
  549.       rl_explicit_arg = 1;
  550.     }
  551.       else
  552.     {
  553.       rl_clear_message ();
  554.       rl_stuff_char (key);
  555.       break;
  556.     }
  557.     }
  558. }
  559.  
  560. void rl_vi_delete_to (int count, int key)
  561. {
  562.   int c;
  563.  
  564.   if (uppercase_p (key))
  565.     rl_stuff_char ('$');
  566.  
  567.   if (rl_vi_domove (key, &c))
  568.     {
  569.       ding ();
  570.       return;
  571.     }
  572.  
  573.   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
  574.     rl_mark++;
  575.  
  576.   rl_kill_text (rl_point, rl_mark);
  577. }
  578.  
  579. void rl_vi_change_to (int count, int key)
  580. {
  581.   int c;
  582.  
  583.   if (uppercase_p (key))
  584.     rl_stuff_char ('$');
  585.  
  586.   if (rl_vi_domove (key, &c))
  587.     {
  588.       ding ();
  589.       return;
  590.     }
  591.  
  592.   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
  593.     rl_mark++;
  594.  
  595.   rl_begin_undo_group ();
  596.   vi_doing_insert = 1;
  597.   rl_kill_text (rl_point, rl_mark);
  598.   rl_vi_insertion_mode (0, 0);
  599. }
  600.  
  601. void rl_vi_yank_to (int count, int key)
  602. {
  603.   int c, save = rl_point;
  604.  
  605.   if (uppercase_p (key))
  606.     rl_stuff_char ('$');
  607.  
  608.   if (rl_vi_domove (key, &c))
  609.     {
  610.       ding ();
  611.       return;
  612.     }
  613.  
  614.   rl_begin_undo_group ();
  615.   rl_kill_text (rl_point, rl_mark);
  616.   rl_end_undo_group ();
  617.   rl_do_undo ();
  618.   rl_point = save;
  619. }
  620.  
  621. void rl_vi_delete (int count, int dum2)
  622. {
  623.   int end;
  624.  
  625.   if (rl_end == 0)
  626.     {
  627.       ding ();
  628.       return;
  629.     }
  630.  
  631.   end = rl_point + count;
  632.  
  633.   if (end >= rl_end)
  634.     end = rl_end;
  635.  
  636.   rl_kill_text (rl_point, end);
  637.   
  638.   if (rl_point > 0 && rl_point == rl_end)
  639.     rl_backward (1, 0);
  640. }
  641.  
  642. /* Turn the current line into a comment in shell history.
  643.    A K*rn shell style function. */
  644. void rl_vi_comment (int dum1, int dum2)
  645. {
  646.   rl_beg_of_line(0, 0);
  647.   rl_insert_text (": ");    /* `#' doesn't work in interactive mode */
  648.   rl_redisplay ();
  649.   rl_newline (1, '\010');
  650. }
  651.  
  652. void rl_vi_first_print (int dum1, int dum2)
  653. {
  654.   rl_back_to_indent ();
  655. }
  656.  
  657. void rl_back_to_indent ()
  658. {
  659.   rl_beg_of_line(0, 0);
  660.   while (rl_point < rl_end && whitespace (the_line[rl_point]))
  661.     rl_point++;
  662. }
  663.  
  664. /* NOTE: it is necessary that opposite directions are inverses */
  665. #define    FTO     1        /* forward to */
  666. #define BTO    -1        /* backward to */
  667. #define FFIND     2        /* forward find */
  668. #define BFIND    -2        /* backward find */
  669.  
  670. void rl_vi_char_search (int count, int key)
  671. {
  672.   static char target;
  673.   static int orig_dir, dir;
  674.   int pos;
  675.  
  676.   if (key == ';' || key == ',')
  677.     dir = (key == ';' ? orig_dir : -orig_dir);
  678.   else
  679.     {
  680.       target = rl_getc (in_stream);
  681.  
  682.       switch (key)
  683.     {
  684.     case 't':
  685.       orig_dir = dir = FTO;
  686.       break;
  687.  
  688.     case 'T':
  689.       orig_dir = dir = BTO;
  690.       break;
  691.  
  692.     case 'f':
  693.       orig_dir = dir = FFIND;
  694.       break;
  695.  
  696.     case 'F':
  697.       orig_dir = dir = BFIND;
  698.       break;
  699.     }
  700.     }
  701.  
  702.   pos = rl_point;
  703.  
  704.   if (dir < 0)
  705.     {
  706.       pos--;
  707.       do
  708.     {
  709.       if (the_line[pos] == target)
  710.         {
  711.           if (dir == BTO)
  712.         rl_point = pos + 1;
  713.           else
  714.         rl_point = pos;
  715.           return;
  716.         }
  717.     }
  718.       while (pos--);
  719.  
  720.       if (pos < 0)
  721.     {
  722.       ding ();
  723.       return;
  724.     }
  725.     }
  726.   else
  727.     {            /* dir > 0 */
  728.       pos++;
  729.       do
  730.     {
  731.       if (the_line[pos] == target)
  732.         {
  733.           if (dir == FTO)
  734.         rl_point = pos - 1;
  735.           else
  736.         rl_point = pos;
  737.           return;
  738.         }
  739.     }
  740.       while (++pos < rl_end);
  741.  
  742.       if (pos >= (rl_end - 1))
  743.     ding ();
  744.     }
  745. }
  746.  
  747. /* Match brackets */
  748. void rl_vi_match (int dum1, int dum2)
  749. {
  750.   int count = 1, brack, pos;
  751.  
  752.   pos = rl_point;
  753.   if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
  754.     {
  755.       while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
  756.          rl_point < rl_end - 1)
  757.     rl_forward (1, 0);
  758.  
  759.       if (brack <= 0)
  760.     {
  761.       rl_point = pos;
  762.       ding ();
  763.       return;
  764.     }
  765.     }
  766.  
  767.   pos = rl_point;
  768.  
  769.   if (brack < 0)
  770.     {
  771.       while (count)
  772.     {
  773.       if (--pos >= 0)
  774.         {
  775.           int b = rl_vi_bracktype (the_line[pos]);
  776.           if (b == -brack)
  777.         count--;
  778.           else if (b == brack)
  779.         count++;
  780.         }
  781.       else
  782.         {
  783.           ding ();
  784.           return;
  785.         }
  786.     }
  787.     }
  788.   else
  789.     {            /* brack > 0 */
  790.       while (count)
  791.     {
  792.       if (++pos < rl_end)
  793.         {
  794.           int b = rl_vi_bracktype (the_line[pos]);
  795.           if (b == -brack)
  796.         count--;
  797.           else if (b == brack)
  798.         count++;
  799.         }
  800.       else
  801.         {
  802.           ding ();
  803.           return;
  804.         }
  805.     }
  806.     }
  807.   rl_point = pos;
  808. }
  809.  
  810. int rl_vi_bracktype (int c)
  811. {
  812.   switch (c)
  813.     {
  814.     case '(': return  1;
  815.     case ')': return -1;
  816.     case '[': return  2;
  817.     case ']': return -2;
  818.     case '{': return  3;
  819.     case '}': return -3;
  820.     default:  return  0;
  821.     }
  822. }
  823.  
  824. void rl_vi_change_char (int dum1, int dum2)
  825. {
  826.   int c;
  827.  
  828.   c = rl_getc (in_stream);
  829.  
  830.   switch (c)
  831.     {
  832.     case '\033':
  833.     case CTRL('C'):
  834.       return;
  835.  
  836.     default:
  837.       rl_begin_undo_group ();
  838.       rl_delete (1, c);
  839.       rl_insert (1, c);
  840.       rl_end_undo_group ();
  841.       break;
  842.     }
  843. }
  844.  
  845. void rl_vi_subst (int count, int key)
  846. {
  847.   rl_begin_undo_group ();
  848.   vi_doing_insert = 1;
  849.  
  850.   if (uppercase_p (key))
  851.     {
  852.       rl_beg_of_line(0, 0);
  853.       rl_kill_line (1, 0);
  854.     }
  855.   else
  856.     rl_delete (count, key);
  857.  
  858.   rl_vi_insertion_mode (0, 0);
  859. }
  860.  
  861. void rl_vi_overstrike (int count, int key)
  862. {
  863.   int i;
  864.  
  865.   if (vi_doing_insert == 0)
  866.     {
  867.       vi_doing_insert = 1;
  868.       rl_begin_undo_group ();
  869.     }
  870.  
  871.   for (i = 0; i < count; i++)
  872.     {
  873.       vi_replace_count++;
  874.       rl_begin_undo_group ();
  875.  
  876.       if (rl_point < rl_end)
  877.     {
  878.       rl_delete (1, key);
  879.       rl_insert (1, key);
  880.     }
  881.       else
  882.     rl_insert (1, key);
  883.  
  884.       rl_end_undo_group ();
  885.     }
  886. }
  887.  
  888. void rl_vi_overstrike_delete (int count, int dum2)
  889. {
  890.   int i, s;
  891.  
  892.   for (i = 0; i < count; i++)
  893.     {
  894.       if (vi_replace_count == 0)
  895.     {
  896.       ding ();
  897.       break;
  898.     }
  899.       s = rl_point;
  900.  
  901.       if (rl_do_undo ())
  902.     vi_replace_count--;
  903.  
  904.       if (rl_point == s)
  905.     rl_backward (1, 0);
  906.     }
  907.  
  908.   if (vi_replace_count == 0 && vi_doing_insert)
  909.     {
  910.       rl_end_undo_group ();
  911.       rl_do_undo ();
  912.       vi_doing_insert = 0;
  913.     }
  914. }
  915.  
  916. void rl_vi_replace (int dum1, int dum2)
  917. {
  918.   int i;
  919.  
  920.   vi_replace_count = 0;
  921.  
  922.   vi_replace_map = rl_make_bare_keymap ();
  923.  
  924.   for (i = ' '; i < 127; i++)
  925.     vi_replace_map[i].function = rl_vi_overstrike;
  926.  
  927.   vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
  928.   vi_replace_map[ESC].function = rl_vi_movement_mode;
  929.   vi_replace_map[RETURN].function = rl_newline;
  930.   vi_replace_map[NEWLINE].function = rl_newline;
  931.   keymap = vi_replace_map;
  932. }
  933.  
  934. /*
  935.  * Try to complete the word we are standing on or the word that ends with
  936.  * the previous character. A space matches everything.
  937.  * Word delimiters are space and ;.
  938.  */
  939. void rl_vi_possible_completions (int dum1, int dum2)
  940. {
  941.   int save_pos = rl_point;
  942.  
  943.   if (!strchr (" ;", the_line[rl_point]))
  944.     {
  945.       while (!strchr(" ;", the_line[++rl_point]))
  946.     ;
  947.     }
  948.   else if (the_line[rl_point-1] == ';')
  949.     {
  950.       ding ();
  951.       return;
  952.     }
  953.  
  954.   rl_possible_completions (0, 0);
  955.   rl_point = save_pos;
  956.  
  957.   return;
  958. }
  959.